package com.kool.kmetrics.common.util;

import com.kool.kmetrics.common.constant.ErrorCode;
import com.kool.kmetrics.common.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description 文件工具
 * @Author luyu
 * @Date 2019/4/10 9:40
 **/
@Slf4j
public class FileUtil {

    public static byte[] readBytes(String filePath) {
        if (StringUtils.isEmpty(filePath)) {
            // 文件路径为空!
            String errUid = StringUtil.getUUID();
            log.error("{}: 文件路径为空", errUid);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        }

        FileInputStream fileInputStream = null;
        BufferedInputStream bufferedInputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        byte[] retBytes;
        try {
            fileInputStream = new FileInputStream(filePath);
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buff = new byte[1024];
            int hasRead = 0;
            while ((hasRead = bufferedInputStream.read(buff)) != -1) {
                byteArrayOutputStream.write(buff, 0, hasRead);
            }
            retBytes = byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                    fileInputStream = null;
                }
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                    bufferedInputStream = null;
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                    byteArrayOutputStream = null;
                }
            } catch (IOException e) {
                String errUid = StringUtil.getUUID();
                log.error(errUid, e);
                // 系统异常，请联系管理员！异常码：%s
                throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
            }
        }
        return retBytes;
    }

    public static void writeBytesFromFile(String from, String to, boolean append) {
        if (StringUtils.isEmpty(from)) {
            // 文件路径为空!
            String errUid = StringUtil.getUUID();
            log.error("{}: 文件路径为空", errUid);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        }
        if (StringUtils.isEmpty(to)) {
            // 文件路径为空!
            String errUid = StringUtil.getUUID();
            log.error("{}: 文件路径为空", errUid);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        }

        FileInputStream fileInputStream = null;
        BufferedInputStream bufferedInputStream = null;
        FileOutputStream fileOutputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {
            fileInputStream = new FileInputStream(from);
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            fileOutputStream = new FileOutputStream(to, append);
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            byte[] buff = new byte[1024];
            int hasRead = 0;
            while ((hasRead = bufferedInputStream.read(buff)) != -1) {
                bufferedOutputStream.write(buff, 0, hasRead);
            }
            bufferedOutputStream.flush();

        } catch (Exception e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                    fileInputStream = null;
                }
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                    bufferedInputStream = null;
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                    fileOutputStream = null;
                }
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                    bufferedOutputStream = null;
                }
            } catch (IOException e) {
                String errUid = StringUtil.getUUID();
                log.error(errUid, e);
                // 系统异常，请联系管理员！异常码：%s
                throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
            }
        }
    }

    /**
     * @param sFilePath 文件路径
     * @param sCharset  文件的编码集，为空时使用默认值UTF-8
     * @return 文件内容字符串
     * @DESCRIBE 从文件中读取字符串，返回字符串
     */
    public static String readFile(String sFilePath, String sCharset) {
        if (StringUtils.isEmpty(sFilePath)) {
            // 文件路径为空!
            String errUid = StringUtil.getUUID();
            log.error("{}: 文件路径为空", errUid);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        }
        if (StringUtils.isEmpty(sCharset)) {
            sCharset = "UTF-8";
        }
        String sContext = null;
        File fInput = new File(sFilePath);

        if (fInput.exists() == false) {
            // 文件不存在
            String errUid = StringUtil.getUUID();
            log.error("{}: 文件不存在", errUid);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        }
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            fis = new FileInputStream(fInput);
            isr = new InputStreamReader(fis, sCharset);
            br = new BufferedReader(isr);
            char[] cBuff = new char[1000];
            int iHasRead = 0;
            StringBuffer sbTemp = new StringBuffer();
            while ((iHasRead = br.read(cBuff)) != -1) {
                sbTemp.append(cBuff, 0, iHasRead);
            }
            sContext = sbTemp.toString();
        } catch (FileNotFoundException e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
        } catch (UnsupportedEncodingException e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
        } catch (IOException e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                    fis = null;
                }
                if (isr != null) {
                    isr.close();
                    isr = null;
                }
                if (br != null) {
                    br.close();
                    br = null;
                }
            } catch (IOException e) {
                String errUid = StringUtil.getUUID();
                log.error(errUid, e);
                // 系统异常，请联系管理员！异常码：%s
                throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
            }
        }

        return sContext;
    }

    /**
     * 读取文件
     * 编码：utf-8
     *
     * @param filePath
     * @return
     */
    public static String readFile(String filePath) {
        return readFile(filePath, "utf-8");
    }

    /**
     * @param content   字符串
     * @param sFilePath 文件路径
     * @param sCharset  文件编码集，为空时使用默认值UTF-8
     * @param append    true末尾追加内容，false覆盖内容
     * @DESCRIBE 将字符串写入文件
     */
    public static void writeFile(String content, String sFilePath, String sCharset, boolean append) {
        if (StringUtils.isEmpty(sFilePath)) {
            // 文件路径为空!
            String errUid = StringUtil.getUUID();
            log.error("{}: 文件路径为空", errUid);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        }
        if (StringUtils.isEmpty(sCharset)) {
            sCharset = "UTF-8";
        }

        File fOutput = new File(sFilePath);
        File fDir = fOutput.getParentFile();
        if (fDir.exists() == false) {
            fDir.mkdirs();
        }

        FileOutputStream fos = null;
        try {
            if (fOutput.exists() == false) {
                fOutput.createNewFile();
            }
            fos = new FileOutputStream(fOutput, append);
            fos.write(content.getBytes(sCharset));
            fos.flush();

        } catch (FileNotFoundException e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
        } catch (UnsupportedEncodingException e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
        } catch (IOException e) {
            String errUid = StringUtil.getUUID();
            log.error(errUid, e);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                    fos = null;
                }
            } catch (IOException e) {
                String errUid = StringUtil.getUUID();
                log.error(errUid, e);
                // 系统异常，请联系管理员！异常码：%s
                throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), e, errUid);
            }
        }
    }

    /**
     * @return
     * @DESCRIBE 获取操作系统的文件路径分隔符
     */
    public static String getSeparator() {
        return System.getProperty("file.separator");
    }


    /**
     * 删除文件
     *
     * @param sFilePath
     */
    public static void deleteFile(String sFilePath) {
        if (StringUtils.isEmpty(sFilePath)) {
            String errUid = StringUtil.getUUID();
            log.error("{}: 文件路径为空", errUid);
            // 系统异常，请联系管理员！异常码：%s
            throw new AppException(ErrorCode.SYSTEM_ERROR.getCode(), errUid);
        }
        File file = new File(sFilePath);
        if (file.exists()) {
            file.delete();
        }
    }

    /**
     * 删除文件或文件夹
     * 如果文件夹被占用则不删除
     *
     * @param dirPath
     */
    public static void deleteDirOrFile(String dirPath) {
        if (StringUtil.isEmpty(dirPath)) {
            return;
        }
        File parentFile = new File(dirPath);
        if (!parentFile.exists()) {
            return;
        }
        if (parentFile.isFile()) {
            //如果传入是文件，删除文件
           deleteFile(parentFile.getAbsolutePath());
        } else {
            File[] subFiles = parentFile.listFiles();
            //如果传入是文件夹，非空，删除文件夹中文件
            if (subFiles != null && subFiles.length > 0) {
                for (File file : subFiles) {
                    if (file.isFile()) {
                        deleteFile(file.getAbsolutePath());
                    }else{
                        deleteDirOrFile(file.getAbsolutePath());
                    }
                }

            }
            //删除文件夹
            deleteFile(parentFile.getAbsolutePath());
        }

    }

    /**
     * 遍历路径下所有文件
     *
     * @param path
     * @return
     */
    public static List<File> getAllFiles(String path) {
        if (StringUtil.isEmpty(path)) {
            return null;
        }
        File rootFile = new File(path);
        if (!rootFile.exists()) {
            return null;
        }
        List<File> files = new ArrayList<>();
        if (rootFile.isFile()) {
            files.add(rootFile);
        } else {
            files.addAll(getAllFiles(rootFile));
        }
        return files;
    }

    private static List<File> getAllFiles(File dir) {
        List<File> files = new ArrayList<>();
        File[] subFiles = dir.listFiles();
        for (File subFile : subFiles) {
            if (subFile.isFile()) {
                files.add(subFile);
                log.debug(subFile.getAbsolutePath());
            } else {
                files.addAll(getAllFiles(subFile));
            }
        }
        return files;
    }

}
